Previous slide Next slide Toggle fullscreen Open presenter view
Программирование сетевых приложений
Основы QT
Программирование сетевых приложений
Содержание лекции
Введение в Qt
История и развитие Qt
Архитектура и основные принципы Qt
Модульная структура Qt
Метаобъектная система (MOC)
Сигналы и слоты
Событийная система Qt
Управление памятью
Инструменты разработки Qt
Qt Network — TCP-сервер и UDP-сокеты
HTTP-запросы и QNetworkAccessManager
Многопоточность и сетевые операции
SSL/TLS в Qt Network
Преимущества и недостатки Qt
Программирование сетевых приложений
Введение в Qt
Что такое Qt?
Qt - это кроссплатформенный фреймворк для разработки приложений с графическим интерфейсом
Основные характеристики
Кроссплатформенность - Windows, macOS, Linux, Android, iOS
Богатая функциональность - GUI, сети, базы данных, мультимедиа
Высокая производительность - нативные приложения
Обширная документация и сообщество
Коммерческая и open source лицензии
Области применения
Десктопные приложения - офисные программы, IDE
Мобильные приложения - Android и iOS
Встроенные системы - IoT устройства
Автомобильная промышленность - приборные панели
Промышленная автоматизация - SCADA системы
Программирование сетевых приложений
История и развитие Qt
Ключевые этапы развития
1995 год - Qt 1.0, основание Trolltech (Ховард Норд и Айрик Чамб-Энг)
1999 год - Qt 2.0 с поддержкой UNIX и Windows
2001 год - Qt 3.0, расширение платформ
2005 год - Qt 4.0 с новой модульной архитектурой
2008 год - приобретение Nokia
2010 год - Qt 4.7, появление Qt Quick и QML
2012 год - Qt 5.0 с QML как основой UI
2014 год - создание The Qt Company после выделения из Digia
2020 год - Qt 6.0 с улучшенной производительностью и C++17
Эволюция подходов
Qt Widgets - классический подход к GUI
Qt Quick - современный декларативный UI
QML - язык описания интерфейса
Qt 3D - 3D графика и анимации
Qt WebEngine - встроенный браузерный движок
Программирование сетевых приложений
Архитектура и основные принципы Qt
Архитектурные принципы
Модульность - независимые компоненты
Переносимость - единый код для всех платформ
Расширяемость - возможность создания собственных компонентов
Производительность - нативная компиляция
Обратная совместимость - поддержка старых версий
Основные концепции
Объектная модель - наследование от QObject
Событийная система - обработка событий
Сигналы и слоты - механизм взаимодействия
Метаобъектная система - рефлексия в C++
Управление памятью - автоматическое управление ресурсами
Программирование сетевых приложений
Модульная структура Qt
Основные модули Qt6
Модуль
Назначение
Примеры использования
Qt Core
Базовые классы и функциональность
QObject, QVariant, контейнеры
Qt GUI
Базовые классы GUI
QWidget, QApplication, события
Qt Widgets
Классические элементы интерфейса
QPushButton, QLineEdit, QTableWidget
Qt Quick
Современный декларативный UI
QML, анимации, сенсорный ввод
Qt Network
Сетевое программирование
QTcpSocket, QUdpSocket, HTTP
Qt SQL
Работа с базами данных
QSqlDatabase, QSqlQuery
Qt Multimedia
Аудио, видео, камера
QMediaPlayer, QCamera
Qt WebEngine
Веб-браузер и движок
WebView, JavaScript интеграция
Программирование сетевых приложений
Метаобъектная система (MOC)
Что такое MOC?
Meta-Object Compiler (MOC) - препроцессор, генерирующий дополнительный код для поддержки метаобъектной системы
Возможности MOC
Сигналы и слоты - механизм событий
Информация о типах - RTTI (Runtime Type Information)
Свойства объектов - динамические свойства
Трансляция строк - поддержка интернационализации
Программирование сетевых приложений
Пример использования MOC
#include <QObject>
#include <QDebug>
class NetworkManager : public QObject {
Q_OBJECT
Q_PROPERTY (QString status READ getStatus WRITE setStatus NOTIFY statusChanged)
Q_PROPERTY (int connectionCount READ getConnectionCount)
public :
explicit NetworkManager (QObject* parent = nullptr )
: QObject(parent), m_status("Disconnected" ), m_connectionCount(0 ) { }
QString getStatus () const { return m_status; }
void setStatus (const QString& status) {
if (m_status != status) {
m_status = status;
emit statusChanged (status) ;
}
}
int getConnectionCount () const { return m_connectionCount; }
signals:
void statusChanged (const QString& newStatus) ;
void connectionEstablished (const QString& address) ;
void connectionLost (const QString& address) ;
public slots:
void connectToServer (const QString& address, int port) {
qDebug () << "Подключение к серверу:" << address << ":" << port;
setStatus ("Connecting..." );
}
void disconnectFromServer () {
qDebug () << "Отключение от сервера" ;
setStatus ("Disconnected" );
}
private :
QString m_status;
int m_connectionCount;
};
Программирование сетевых приложений
Сигналы и слоты
Основные принципы
Сигналы - уведомления о событиях
Слоты - обработчики событий
Соединения - связывание сигналов со слотами
Автоматическое управление - нет необходимости в ручном вызове
Программирование сетевых приложений
Типы соединений
#include <QObject>
#include <QTimer>
#include <QDebug>
class ConnectionExample : public QObject {
Q_OBJECT
public :
ConnectionExample (QObject* parent = nullptr ) : QObject (parent) {
connect (&timer, &QTimer::timeout, this , &ConnectionExample::onTimeout);
connect (&timer, &QTimer::timeout, this , &ConnectionExample::onTimeout, Qt::QueuedConnection);
connect (&timer, &QTimer::timeout, []() {
qDebug () << "Таймер сработал!" ;
});
}
public slots:
void onTimeout () {
qDebug () << "Обработка таймера" ;
}
signals:
void dataReceived (const QByteArray& data) ;
void connectionStateChanged (bool connected) ;
private :
QTimer timer;
};
Программирование сетевых приложений
Событийная система Qt
Иерархия событий
QEvent - базовый класс всех событий
QMouseEvent - события мыши
QKeyEvent - события клавиатуры
QResizeEvent - изменение размера
QPaintEvent - перерисовка
QCloseEvent - закрытие окна
Программирование сетевых приложений
Обработка событий
#include <QWidget>
#include <QMouseEvent>
#include <QKeyEvent>
#include <QPaintEvent>
#include <QDebug>
class CustomWidget : public QWidget {
Q_OBJECT
public :
CustomWidget (QWidget* parent = nullptr ) : QWidget (parent) {
setMouseTracking (true );
}
protected :
void mousePressEvent (QMouseEvent* event) override {
qDebug () << "Нажата кнопка мыши:" << event->button ()
<< "в позиции:" << event->pos ();
if (event->button () == Qt::LeftButton) {
update ();
}
}
void mouseMoveEvent (QMouseEvent* event) override {
qDebug () << "Перемещение мыши:" << event->pos ();
}
void mouseReleaseEvent (QMouseEvent* event) override {
qDebug () << "Отпущена кнопка мыши:" << event->button ();
}
void keyPressEvent (QKeyEvent* event) override {
qDebug () << "Нажата клавиша:" << event->key ()
<< "текст:" << event->text ();
if (event->key () == Qt::Key_Escape) {
close ();
}
}
void paintEvent (QPaintEvent* event) override {
QPainter painter (this ) ;
painter.fillRect (rect (), Qt::blue);
painter.drawText (rect (), Qt::AlignCenter, "Кастомный виджет" );
}
void resizeEvent (QResizeEvent* event) override {
qDebug () << "Размер изменен:" << event->oldSize ()
<< "->" << event->size ();
}
};
Программирование сетевых приложений
Управление памятью
Родительско-дочерние отношения
#include <QWidget>
#include <QVBoxLayout>
#include <QPushButton>
#include <QLabel>
class MemoryManagementExample : public QWidget {
Q_OBJECT
public :
MemoryManagementExample (QWidget* parent = nullptr )
: QWidget (parent) {
QVBoxLayout* layout = new QVBoxLayout (this );
QLabel* label = new QLabel ("Пример управления памятью" , this );
QPushButton* button = new QPushButton ("Нажми меня" , this );
layout->addWidget (label);
layout->addWidget (button);
}
};
Программирование сетевых приложений
Умные указатели в Qt
#include <QObject>
#include <QSharedPointer>
#include <QWeakPointer>
class SmartPointerExample : public QObject {
Q_OBJECT
public :
void demonstrateSmartPointers () {
QSharedPointer<QObject> sharedObj (new QObject()) ;
QSharedPointer<QObject> sharedObj2 = sharedObj;
QWeakPointer<QObject> weakObj = sharedObj;
if (!weakObj.isNull ()) {
QSharedPointer<QObject> strongRef = weakObj.toStrongRef ();
}
}
};
Программирование сетевых приложений
Инструменты разработки Qt
Qt Creator
IDE для разработки Qt приложений
Визуальный дизайнер интерфейсов
Отладчик и профилировщик
Поддержка QML и C++
Программирование сетевых приложений
Qt Designer
#include <QApplication>
#include <QWidget>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QPushButton>
#include <QLineEdit>
#include <QLabel>
int main (int argc, char *argv[]) {
QApplication app (argc, argv) ;
QWidget window;
window.setWindowTitle ("Пример Qt приложения" );
window.resize (400 , 300 );
QVBoxLayout* mainLayout = new QVBoxLayout;
QHBoxLayout* inputLayout = new QHBoxLayout;
QLabel* nameLabel = new QLabel ("Имя:" );
QLineEdit* nameEdit = new QLineEdit;
inputLayout->addWidget (nameLabel);
inputLayout->addWidget (nameEdit);
QHBoxLayout* buttonLayout = new QHBoxLayout;
QPushButton* okButton = new QPushButton ("OK" );
QPushButton* cancelButton = new QPushButton ("Отмена" );
buttonLayout->addWidget (okButton);
buttonLayout->addWidget (cancelButton);
mainLayout->addLayout (inputLayout);
mainLayout->addLayout (buttonLayout);
window.setLayout (mainLayout);
window.show ();
return app.exec ();
}
Программирование сетевых приложений
qmake и CMake
cmake_minimum_required (VERSION 3.16 )
project (QtExample)
set (CMAKE_CXX_STANDARD 17 )
set (CMAKE_CXX_STANDARD_REQUIRED ON )
find_package (Qt6 COMPONENTS Core Widgets REQUIRED)
add_executable (QtExample main.cpp)
target_link_libraries (QtExample PRIVATE Qt6::Core Qt6::Widgets)
set_target_properties (QtExample PROPERTIES
AUTOMOC ON
AUTOUIC ON
AUTORCC ON
)
Программирование сетевых приложений
Преимущества Qt
Технические преимущества
Кроссплатформенность - один код для всех платформ
Производительность - нативная компиляция
Богатая функциональность - готовые компоненты
Зрелость - более 30 лет развития
Документация - подробная документация и примеры
Разработческие преимущества
Быстрая разработка - готовые компоненты
Визуальное проектирование - Qt Designer
Сообщество - большое сообщество разработчиков
Поддержка - коммерческая и техническая поддержка
Программирование сетевых приложений
Недостатки Qt
Технические ограничения
Размер исполняемых файлов - большие бинарники
Зависимости - требуется Qt библиотеки
Производительность QML - может быть медленнее нативного кода
Лицензирование - коммерческая лицензия для некоторых случаев
Разработческие ограничения
Изучение - требует времени для освоения
Специфичность - нестандартный подход к программированию
Экосистема - меньше библиотек по сравнению с другими платформами
Программирование сетевых приложений
Сравнение с альтернативами
Qt vs другие фреймворки
Критерий
Qt
WPF
JavaFX
Electron
Кроссплатформенность
Отличная
Windows
Хорошая
Отличная
Производительность
Высокая
Высокая
Средняя
Низкая
Размер приложения
Средний
Средний
Большой
Очень большой
Нативность
Полная
Полная
Частичная
Веб-технологии
Сообщество
Большое
Среднее
Маленькое
Большое
Лицензия
LGPL/Commercial
MIT (.NET)
GPL/Commercial
MIT
Программирование сетевых приложений
Практические примеры использования
Сетевое приложение на Qt
#include <QApplication>
#include <QTcpSocket>
#include <QTextEdit>
#include <QVBoxLayout>
#include <QPushButton>
#include <QLineEdit>
#include <QWidget>
class NetworkClient : public QWidget {
Q_OBJECT
public :
NetworkClient (QWidget* parent = nullptr ) : QWidget (parent) {
setupUI ();
setupConnections ();
}
private slots:
void connectToServer () {
socket->connectToHost (serverEdit->text (), portEdit->text ().toInt ());
}
void onConnected () {
logEdit->append ("Подключен к серверу" );
}
void onDisconnected () {
logEdit->append ("Отключен от сервера" );
}
void onReadyRead () {
QByteArray data = socket->readAll ();
logEdit->append ("Получено: " + data);
}
void sendMessage () {
if (socket->state () == QAbstractSocket::ConnectedState) {
socket->write (messageEdit->text ().toUtf8 ());
messageEdit->clear ();
}
}
Программирование сетевых приложений
private :
void setupUI () {
QVBoxLayout* layout = new QVBoxLayout;
QHBoxLayout* connectionLayout = new QHBoxLayout;
serverEdit = new QLineEdit ("localhost" );
portEdit = new QLineEdit ("1234" );
connectButton = new QPushButton ("Подключиться" );
connectionLayout->addWidget (new QLabel ("Сервер:" ));
connectionLayout->addWidget (serverEdit);
connectionLayout->addWidget (new QLabel ("Порт:" ));
connectionLayout->addWidget (portEdit);
connectionLayout->addWidget (connectButton);
QHBoxLayout* messageLayout = new QHBoxLayout;
messageEdit = new QLineEdit;
sendButton = new QPushButton ("Отправить" );
messageLayout->addWidget (messageEdit);
messageLayout->addWidget (sendButton);
logEdit = new QTextEdit;
logEdit->setReadOnly (true );
layout->addLayout (connectionLayout);
layout->addLayout (messageLayout);
layout->addWidget (logEdit);
setLayout (layout);
setWindowTitle ("Qt Network Client" );
resize (600 , 400 );
}
Программирование сетевых приложений
void setupConnections () {
socket = new QTcpSocket (this );
connect (connectButton, &QPushButton::clicked, this , &NetworkClient::connectToServer);
connect (sendButton, &QPushButton::clicked, this , &NetworkClient::sendMessage);
connect (socket, &QTcpSocket::connected, this , &NetworkClient::onConnected);
connect (socket, &QTcpSocket::disconnected, this , &NetworkClient::onDisconnected);
connect (socket, &QTcpSocket::readyRead, this , &NetworkClient::onReadyRead);
}
QTcpSocket* socket;
QLineEdit* serverEdit;
QLineEdit* portEdit;
QLineEdit* messageEdit;
QPushButton* connectButton;
QPushButton* sendButton;
QTextEdit* logEdit;
};
int main (int argc, char *argv[]) {
QApplication app (argc, argv) ;
NetworkClient client;
client.show ();
return app.exec ();
}
Программирование сетевых приложений
Qt Network — обзор возможностей
Классы для сетевого программирования
Класс
Назначение
Протокол
QTcpSocket
TCP-клиент
TCP
QTcpServer
TCP-сервер
TCP
QUdpSocket
Дейтаграммная передача
UDP
QNetworkAccessManager
HTTP/HTTPS запросы
HTTP(S)
QNetworkReply
Ответ HTTP-запроса
HTTP(S)
QSslSocket
Зашифрованное соединение
TLS/SSL
QWebSocket
Полнодуплексный канал
WebSocket
QHostInfo
DNS-разрешение имён
DNS
QNetworkInterface
Информация о сетевых интерфейсах
—
Программирование сетевых приложений
TCP-сервер на Qt
Пример эхо-сервера
#include <QTcpServer>
#include <QTcpSocket>
#include <QDateTime>
class EchoServer : public QObject {
Q_OBJECT
public :
explicit EchoServer (quint16 port, QObject* parent = nullptr )
: QObject(parent) {
server = new QTcpServer (this );
connect (server, &QTcpServer::newConnection, this , &EchoServer::onNewConnection);
if (server->listen (QHostAddress::Any, port)) {
qDebug () << "Сервер запущен на порту" << port;
} else {
qDebug () << "Ошибка запуска:" << server->errorString ();
}
}
private slots:
void onNewConnection () {
QTcpSocket* client = server->nextPendingConnection ();
qDebug () << "Новое подключение:" << client->peerAddress ().toString ();
connect (client, &QTcpSocket::readyRead, [client]() {
QByteArray data = client->readAll ();
qDebug () << "Получено:" << data;
client->write ("Echo: " + data);
});
connect (client, &QTcpSocket::disconnected, client, &QTcpSocket::deleteLater);
}
private :
QTcpSocket* server;
};
Примечание : deleteLater гарантирует безопасное удаление сокета после завершения обработки текущего события.
Программирование сетевых приложений
UDP-сокеты в Qt
Дейтаграммная передача
#include <QUdpSocket>
#include <QNetworkDatagram>
class UdpChat : public QObject {
Q_OBJECT
public :
UdpChat (quint16 port, QObject* parent = nullptr ) : QObject (parent) {
socket = new QUdpSocket (this );
socket->bind (QHostAddress::Any, port, QAbstractSocket::ShareAddress);
connect (socket, &QUdpSocket::readyRead, this , &UdpChat::onReadyRead);
}
void sendMessage (const QString& message, const QHostAddress& address, quint16 port) {
QByteArray data = message.toUtf8 ();
socket->writeDatagram (data, address, port);
}
private slots:
void onReadyRead () {
while (socket->hasPendingDatagrams ()) {
QNetworkDatagram datagram = socket->receiveDatagram ();
qDebug () << "От:" << datagram.senderAddress () << datagram.senderPort ()
<< "Сообщение:" << datagram.data ();
}
}
private :
QUdpSocket* socket;
};
Программирование сетевых приложений
HTTP-запросы с QNetworkAccessManager
Асинхронные HTTP-запросы
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QJsonDocument>
#include <QJsonObject>
class HttpClient : public QObject {
Q_OBJECT
public :
explicit HttpClient (QObject* parent = nullptr ) : QObject(parent) {
manager = new QNetworkAccessManager (this );
connect (manager, &QNetworkAccessManager::finished,
this , &HttpClient::onReplyFinished);
}
void getRequest (const QUrl& url) {
QNetworkRequest request (url) ;
request.setHeader (QNetworkRequest::ContentTypeHeader, "application/json" );
manager->get (request);
}
void postRequest (const QUrl& url, const QJsonObject& data) {
QNetworkRequest request (url) ;
request.setHeader (QNetworkRequest::ContentTypeHeader, "application/json" );
manager->post (request, QJsonDocument (data).toJson ());
}
private slots:
void onReplyFinished (QNetworkReply* reply) {
if (reply->error () == QNetworkReply::NoError) {
QByteArray response = reply->readAll ();
QJsonDocument doc = QJsonDocument::fromJson (response);
qDebug () << "Ответ:" << doc.toJson ();
} else {
qDebug () << "Ошибка HTTP:" << reply->errorString ();
}
reply->deleteLater ();
}
private :
QNetworkAccessManager* manager;
};
Программирование сетевых приложений
Многопоточность и сеть
QThread + сетевые операции
#include <QThread>
#include <QTcpSocket>
#include <QMutex>
class NetworkWorker : public QObject {
Q_OBJECT
public slots:
void doConnect (const QString& host, quint16 port) {
QTcpSocket socket;
socket.connectToHost (host, port);
if (socket.waitForConnected (5000 )) {
emit connected () ;
socket.write ("Hello from thread" );
socket.waitForBytesWritten ();
} else {
emit errorOccurred (socket.errorString ());
}
}
void doLongPolling (const QString& host, quint16 port) {
QTcpSocket socket;
socket.connectToHost (host, port);
if (!socket.waitForConnected (5000 )) return ;
while (!QThread::currentThread ()->isInterruptionRequested ()) {
if (socket.waitForReadyRead (1000 )) {
emit dataReceived (socket.readAll()) ;
}
}
}
signals:
void connected () ;
void dataReceived (const QByteArray& data) ;
void errorOccurred (const QString& error) ;
};
Важно : QTcpSocket нельзя использовать из потока, отличного от того, в котором он был создан. Создавайте сокет внутри doConnect().
Программирование сетевых приложений
SSL/TLS в Qt Network
Защищённые соединения
#include <QSslSocket>
#include <QSslConfiguration>
class SecureClient : public QObject {
Q_OBJECT
public :
void connectSecure (const QString& host, quint16 port) {
QSslSocket* socket = new QSslSocket (this );
connect (socket, &QSslSocket::encrypted, [socket]() {
qDebug () << "SSL-соединение установлено с"
<< socket->peerCertificate ().subjectInfo (QSslCertificate::CommonName);
});
connect (socket, &QSslSocket::sslErrors, [](const QList<QSslError>& errors) {
for (const auto & err : errors)
qDebug () << "SSL ошибка:" << err.errorString ();
});
socket->connectToHostEncrypted (host, port);
}
};
Программирование сетевых приложений
Заключение
Ключевые преимущества Qt
Универсальность - подходит для различных типов приложений
Производительность - нативная компиляция и оптимизация
Сообщество - активная поддержка и развитие
Инструменты - богатая экосистема разработки
Области применения в сетевом программировании
Клиент-серверные приложения - богатые GUI клиенты
Сетевые утилиты - мониторинг, анализ трафика
Встроенные системы - IoT устройства с GUI
Промышленные приложения - SCADA, HMI системы
Перспективы развития
Qt 6 и далее - улучшенная производительность
QML и Qt Quick - современные подходы к UI
Интеграция с веб-технологиями - гибридные приложения
Мобильная разработка - кроссплатформенные мобильные приложения
Программирование сетевых приложений
Вопросы для самопроверки
Что такое MOC и какие возможности он предоставляет?
Как работает механизм сигналов и слотов в Qt?
Какие основные модули входят в состав Qt6?
Как происходит управление памятью в Qt?
В чём преимущества кроссплатформенности Qt?
Какие типы событий поддерживает Qt?
Как создать простое GUI приложение на Qt?
Какие инструменты разработки предоставляет Qt?
В чём отличие Qt Widgets от Qt Quick?
Как создать TCP-сервер на Qt? Объясните роль QTcpServer::newConnection.
Чем отличается QUdpSocket от QTcpSocket? Когда лучше использовать UDP?
Как выполнить HTTP-запрос с помощью QNetworkAccessManager?
Почему QTcpSocket нельзя использовать из другого потока напрямую? Как правильно организовать сетевые операции в отдельном потоке?
Как установить SSL/TLS-соединение с помощью QSslSocket?
Какие недостатки имеет Qt по сравнению с альтернативами?
notes: Эта лекция знакомит с фреймворком Qt как основным инструментом для разработки кроссплатформенных сетевых приложений с GUI. Основной акцент — сетевые возможности Qt, поскольку предыдущие лекции уже рассмотрели низкоуровневые сокеты.
notes: Qt произносится как «кьют» (cute), не «ку-ти». Подчеркнуть, что Qt — не просто GUI-фреймворк, а полноценная платформа с модулями для сети, БД, мультимедиа. Для нашего курса ключевым является модуль Qt Network.
notes: Обратить внимание на ключевые вехи: Qt 4.7 (2010) — появление QML, Qt 5.0 (2012) — переход к QML как основному подходу, Qt 6.0 (2020) — переход на C++17. Актуальная версия на момент лекции — Qt 6.x.
notes: MOC — одна из ключевых особенностей Qt. Это препроцессор, который обрабатывает заголовочные файлы с макросом Q_OBJECT и генерирует дополнительный C++ код. Без MOC сигналы и слоты работать не будут. CMake с AUTOMOC ON автоматически вызывает MOC при сборке.
notes: Сигналы и слоты — центральный паттерн Qt, альтернатива классическим callback-функциям. Преимущества: типобезопасность, слабая связанность (loose coupling), автоматическое отключение при удалении объекта. Рекомендуется использовать новый синтаксис connect с указателями на функции (PMF), а не старый макросный SIGNAL/SLOT.
notes: Qt работает на событийном цикле (QEventLoop). События поступают от ОС (мышь, клавиатура, таймер) и от самой Qt (сигналы). Для сетевого программирования важно понимать, что данные от сокетов также обрабатываются через событийный цикл — readyRead это событие.
notes: Ключевой механизм Qt — родительско-дочерние отношения (parent-child). При удалении родителя автоматически удаляются все дочерние объекты. Это критически важно для GUI и сетевых объектов: при закрытии окна все виджеты и сокеты удаляются автоматически.
notes: Это ключевая секция для нашего курса. Qt Network абстрагирует платформенные различия между Winsock и BSD Sockets (рассмотренными в предыдущих лекциях). Все классы работают через асинхронный событийный цикл Qt — нет необходимости вручную использовать select/poll.
notes: Сравните с TCP-сервером на чистых сокетах из предыдущих лекций — код значительно короче. Обратить внимание на паттерн: newConnection -> nextPendingConnection -> readyRead. deleteLater — идиома Qt для безопасного удаления объектов в цикле событий.
notes: QUdpSocket позволяет отправлять и получать дейтаграммы без установления соединения. QNetworkDatagram (Qt 5.8+) — удобная обёртка, содержащая данные, адрес отправителя и порт. Подходит для широковещательной рассылки (broadcast) и multicast.
notes: QNetworkAccessManager — высокоуровневый API для HTTP/HTTPS. Автоматически управляет соединениями, поддерживает кэширование, cookies, прокси. Все запросы асинхронные — результат приходит через сигнал finished. Для JSON используйте QJsonDocument.
notes: Критически важная тема: QTcpSocket привязан к потоку, в котором создан (thread affinity). Нельзя создать сокет в главном потоке и использовать в другом. Правильный подход: создать сокет внутри метода воркера, который выполняется в рабочем потоке. QThread::isInterruptionRequested() — корректный способ остановить рабочий поток.
notes: QSslSocket наследует QTcpSocket и добавляет шифрование. Метод connectToHostEncrypted выполняет TCP-соединение + TLS-хэндшейк. Обязательно обрабатывать sslErrors — в продакшн-коде нельзя просто игнорировать ошибки сертификата. Qt использует OpenSSL (или платформенные TLS-библиотеки).
notes: Подвести итог: Qt предоставляет все уровни абстракции для сетевого программирования — от низкоуровневых TCP/UDP сокетов до высокоуровневых HTTP-запросов. Для курса «Программирование сетевых приложений» Qt — основной инструмент для создания кроссплатформенных GUI-клиентов и серверов.